import copy
import datetime
from xml.dom import minidom
import pyfo
from base import XMLBase, LinkType
from program import ProgramLink
from computer import ComputerLink, QueueLink
from collection import SimulationLink
from dataset import InputDatasetLink

class UserField:
    _node_name = 'UserField'
    _attrib_map = {'UserField':'value'}    

    def __init__(self, value=None, name=None):
        
        self.value = value
        self.name = name

    def serialize(self):
        schema_attr = {"xmlns":"http://cadac.sdsc.edu/schema",
                       "xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance",
                       "xsi:schemaLocation":"http://cadac.sdsc.edu/schema http://cadac.sdsc.edu/schema/v01/simcat.xsd"}

        if '_attr' in self.__dict__:
            schema_attr.update(self._attr)
        t = self.to_tuple()
        xml = pyfo.pyfo(t, pretty=True, prolog=True, encoding='utf-8')

        return xml

    def toxml(self):
        return self.serialize()

    def __unicode__(self):
        return self.serialize()

    def __str__(self):
        return self.serialize()

    def to_tuple(self):

        if self.name:
            return ('UserField', self.value, {'name':self.name})
        else:
            return ('UserField', self.value)

    def read(self, xml_str):
        xmldoc = minidom.parseString(xml_str)
        node = xmldoc.getElementsByTagName('UserField')[0]
        self.value = node.childNodes[0].data
        name = node.getAttribute('name')
        if name:
            self.name = name

class Tag:
    _node_name = 'Tag'
    _attrib_map = {'Tag':'value'}    

    def __init__(self, value=None):        
        self.value = value

    def serialize(self):
        schema_attr = {"xmlns":"http://cadac.sdsc.edu/schema",
                       "xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance",
                       "xsi:schemaLocation":"http://cadac.sdsc.edu/schema http://cadac.sdsc.edu/schema/v01/simcat.xsd"}

        if '_attr' in self.__dict__:
            schema_attr.update(self._attr)
        t = ('Tag', self.value)
        xml = pyfo.pyfo(t, pretty=True, prolog=True, encoding='utf-8')

        return xml

    def toxml(self):
        return self.serialize()

    def to_tuple(self):
        return ('Tag', self.value)

    def __unicode__(self):
        return self.serialize()

    def __str__(self):
        return self.serialize()

    def read(self, xml_str):
        xmldoc = minidom.parseString(xml_str)
        node = xmldoc.getElementsByTagName('Tag')[0]
        self.value = node.childNodes[0].data


class ParameterSetting:
    _node_name = 'ParameterSetting'
    _attrib_map = {'ParameterSetting':'value'}    

    def __init__(self, value=None, parameter_name=None,
                 parameter=None):
        
        self.value = value
        self.parameter_name = parameter_name
        self.parameter = parameter

    def serialize(self):
        schema_attr = {"xmlns":"http://cadac.sdsc.edu/schema",
                       "xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance",
                       "xsi:schemaLocation":"http://cadac.sdsc.edu/schema http://cadac.sdsc.edu/schema/v01/simcat.xsd"}

        if '_attr' in self.__dict__:
            schema_attr.update(self._attr)
        t = self.to_tuple()
        xml = pyfo.pyfo(t, pretty=True, prolog=True, encoding='utf-8')

        return xml

    def toxml(self):
        return self.serialize()

    def __unicode__(self):
        return self.serialize()

    def __str__(self):
        return self.serialize()

    def to_tuple(self):

        atts = {}
        if self.parameter_name:
            atts['parameter_name'] = self.parameter_name
        if self.parameter:
            atts['parameter'] = self.parameter
        
        if atts:
            return ('ParameterSetting', self.value, atts)
        else:
            return ('ParameterSetting', self.value)

    def read(self, xml_str):
        xmldoc = minidom.parseString(xml_str)
        node = xmldoc.getElementsByTagName('ParameterSetting')[0]
        self.value = node.childNodes[0].data
        parameter = node.getAttribute('parameter')
        if parameter:
            self.parameter = parameter
        parameter_name = node.getAttribute('parameter_name')
        if parameter_name:
            self.parameter_name = parameter_name

class Run(XMLBase):
    _node_name = 'Run'
    _attrib_map = {'Name': 'name',
                   'Description': 'description',
                   'Member':'member',
                   'Version':'version',
                   'Comments':'comments',
                   'ToDo':'todo',
                   'Successful':'successful',
                   'JobID':'jobid',
                   'JobName':'jobname',
                   'Account':'account',
                   'Nodes':'nodes',
                   'TasksPerNode':'tasks_per_node'}
    _attrib_class_map = {'Simulation':{'attribute':'simulation',
                                     'class':SimulationLink},
                         'Program':{'attribute':'program',
                                     'class':ProgramLink},
                         'Computer':{'attribute':'computer',
                                     'class':ComputerLink},
                         'Queue':{'attribute':'queue',
                                  'class':QueueLink}}
    _list_map = {'Tag':{'attribute':'tags',
                        'class':Tag},
                 'UserField':{'attribute':'user_fields',
                              'class':UserField},
                 'ParameterSetting':{'attribute':'parameter_settings',
                                     'class':ParameterSetting},
                 'InputDataset':{'attribute':'input_datasets',
                                     'class':InputDatasetLink}}

    def __init__(self, name=None, description=None, simulation=None,
                 program=None, computer=None, queue=None,
                 parameter_settings=[], input_datasets=[],
                 submit_time=None, wall_clock_limit=None,
                 start_time=None, end_time=None,
                 tags=[], user_fields=[],
                 **kwargs):

        self.name = name
        self.description = description
        self.simulation = simulation
        self.program = program
        self.computer = computer
        self.queue = queue
        self.submit_time = submit_time
        self.wall_clock_limit = wall_clock_limit
        self.start_time = start_time
        self.end_time = end_time
        self.parameter_settings = copy.copy(parameter_settings)
        self.input_datasets = copy.copy(input_datasets)
        self.tags = copy.copy(tags)
        self.user_fields = copy.copy(user_fields)
        self.__dict__.update(kwargs)

    def _build_tuple(self):
        XMLBase._build_tuple(self)
        if self.end_time:
            self._elements.insert(0, ('EndTime', self.end_time.strftime("%Y-%m-%d %H:%M:%S")))
        if self.start_time:
            self._elements.insert(0, ('StartTime', self.start_time.strftime("%Y-%m-%d %H:%M:%S")))
        if self.wall_clock_limit:
            h = self.wall_clock_limit.days*24
            h += self.wall_clock_limit.seconds/3600
            m = (self.wall_clock_limit.seconds % 3600)/60
            s = self.wall_clock_limit.seconds % 60
            limit = '%02d:%02d:%02d' % (h, m, s)
            self._elements.insert(0, ('WallClockLimit', limit))
        if self.submit_time:
            self._elements.insert(0, ('SubmitTime', self.submit_time.strftime("%Y-%m-%d %H:%M:%S")))

    def read(self, xml_str):
        XMLBase.read(self, xml_str)
        nodes = self._xmldoc.getElementsByTagName('WallClockLimit')
        if nodes:
            limit = nodes[0].childNodes[0].data
            limit = limit.split(':')
            h = int(limit[0])
            m = int(limit[1])
            s = int(limit[2])
            self.wall_clock_limit = datetime.timedelta(hours=h, 
                                                       minutes=m, seconds=s)
        nodes = self._xmldoc.getElementsByTagName('SubmitTime')
        if nodes:
            t = nodes[0].childNodes[0].data
            self.submit_time = datetime.datetime.strptime(t, "%Y-%m-%d %H:%M:%S")
        nodes = self._xmldoc.getElementsByTagName('StartTime')
        if nodes:
            t = nodes[0].childNodes[0].data
            self.start_time = datetime.datetime.strptime(t, "%Y-%m-%d %H:%M:%S")
        nodes = self._xmldoc.getElementsByTagName('EndTime')
        if nodes:
            t = nodes[0].childNodes[0].data
            self.end_time = datetime.datetime.strptime(t, "%Y-%m-%d %H:%M:%S")
